// xtree stl/clr header
#ifndef _CLI_XTREE_
 #define _CLI_XTREE_
#include <cliext/functional>	// for Binary/UnaryDelegate
#include <cliext/iterator>

namespace cliext {
	namespace impl {
//
// GENERIC REF CLASS tree_node
//
template<typename _Key_t,
	typename _Value_t>
	ref class tree_node
	:	public _STLCLR Generic::INode<_Value_t>
	{	// tree node
public:
	typedef tree_node<_Key_t, _Value_t> _Mytype_t;
	typedef _STLCLR Generic::INode<_Value_t> _Mynode_it;
	typedef _STLCLR Generic::IBidirectionalContainer<_Value_t> _Mycont_it;
	typedef _Value_t value_type;

	tree_node()
		{	// construct an empty node
		}

	tree_node(_Mytype_t^ _Larg, _Mytype_t^ _Parg,
		_Mytype_t^ _Rarg, _Mytype_t^ _Harg,
		value_type _Val, signed char _Carg)
		:	_Left(_Larg), _Parent(_Parg), _Right(_Rarg),
			_Head(_Harg), _Myval(_Val), _Color(_Carg),
			_Mycont(nullptr)
		{	// construct a node with value
		}

	_Mycont_it^ container()
		{	// return owning container
		return (_Head == nullptr ? nullptr : _Head->_Mycont);
		}

	bool is_head()
		{	// test if head node
		return (_Mycont != nullptr);
		}

	_Mytype_t^ max_node()
		{	// return rightmost node in subtree
		_Mytype_t^ _Node = this;

		for (; !_Node->_Right->is_head(); )
			_Node = _Node->_Right;	// descend along right subtrees
		return (_Node);
		}

	_Mytype_t^ min_node()
		{	// return leftmost node in subtree
		_Mytype_t^ _Node = this;

		for (; !_Node->_Left->is_head(); )
			_Node = _Node->_Left;	// descend along left subtrees
		return (_Node);
		}

	_Mytype_t^ next_node()
		{	// return successor node
		if (this == _Head || _Head == nullptr)
			throw gcnew System::InvalidOperationException();
		else if (!_Right->is_head())
			return (_Right->min_node());
		else
			{	// climb looking for right subtree
			_Mytype_t^ _Node = this;
			_Mytype_t^ _Nextnode;

			for (; !(_Nextnode = _Node->_Parent)->is_head()
				&& _Node == _Nextnode->_Right; )
				_Node = _Nextnode;	// go up while right subtree exists

			return (_Nextnode);	// go to parent (head if end())
			}
		}

	_Mytype_t^ prev_node()
		{	// return predecessor node
		if (_Head == nullptr)
			throw gcnew System::InvalidOperationException();

		if (is_head())
			return(_Right);	// go to rightmost
		else if (!_Left->is_head())
			return (_Left->max_node());	// go to largest on left
		else
			{	// climb looking for left subtree
			_Mytype_t^ _Node = this;
			_Mytype_t^ _Nextnode;

			for (; !(_Nextnode = _Node->_Parent)->is_head()
				&& _Node == _Nextnode->_Left; )
				_Node = _Nextnode;	// go up while left subtree exists

			if (_Nextnode->is_head())
				throw gcnew System::InvalidOperationException();
			return (_Nextnode);	// go to parent (if not head)
			}
		}

	property _Value_t% _Value
		{	// get or set _Myval
		virtual _Value_t% get()
			{	// get _Myval element
			if (this == _Head || _Head == nullptr)
				throw gcnew System::InvalidOperationException();
			return (_Myval);
			}

		virtual void set(_Value_t% _Val)
			{	// set _Myval element
			if (this == _Head || _Head == nullptr)
				throw gcnew System::InvalidOperationException();
			_Myval = _Val;
			}
		};

	// data members
	_Mycont_it^ _Mycont;	// pointer to owning tree
	_Mytype_t^ _Head;	// pointer to head node
	_Mytype_t^ _Left;	// pointer to left subtree
	_Mytype_t^ _Parent;	// pointer to parent
	_Mytype_t^ _Right;	// pointer to right subtree
	value_type _Myval;		// the stored value
	signed char _Color;	// _Red or _Black

private:
	virtual _Mycont_it^ container_virtual() sealed
		= _Mynode_it::container
		{	// return owning container
		return (container());
		}

	virtual bool is_head_virtual() sealed
		= _Mynode_it::is_head
		{	// test if head node
		return (is_head());
		}

	virtual _Mynode_it^ next_node_virtual() sealed
		= _Mynode_it::next_node
		{	// return successor node
		return (next_node());
		}

	virtual _Mynode_it^ prev_node_virtual() sealed
		= _Mynode_it::prev_node
		{	// return predecessor node
		return (prev_node());
		}
	};

//
// TEMPLATE FUNCTION _Key_compare
//
template<typename _Key_t> inline
	bool _Key_compare(_Key_t _Left, _Key_t _Right)
	{	// test if _Left < _Right
	return (_Left < _Right);
	}

inline bool _Key_compare(System::String^ _Left, System::String^ _Right)
	{	// test if _Left < _Right for String
	return (_Left->CompareTo(_Right) < 0);
	}

//
// TEMPLATE CLASS tree
//
template<typename _Traits_t>
	ref class tree
	:	public _Traits_t,
		_STLCLR ITree<typename _Traits_t::key_type,
			typename _Traits_t::value_type>
	{	// ordered red-black tree of elements
public:
	// types
	typedef tree<_Traits_t> _Mytype_t;
	typedef _Traits_t _Mybase_t;
	typedef typename _Traits_t::key_type _Key_t;
	typedef typename _Traits_t::value_type _Value_t;
	typedef _STLCLR ITree<_Key_t, _Value_t> _Mycont_it;
	typedef System::Collections::Generic::IEnumerable<_Value_t> _Myenum_it;
	typedef cli::array<_Value_t> _Myarray_t;

	typedef tree_node<_Key_t, _Value_t> node_type;

	typedef BidirectionalIterator<_Mytype_t>
		iterator;
	typedef ConstBidirectionalIterator<_Mytype_t>
		const_iterator;
	typedef ReverseBidirectionalIterator<_Mytype_t>
		reverse_iterator;
	typedef ReverseBidirectionalIterator<_Mytype_t>
		const_reverse_iterator;

	typedef typename _Traits_t::key_type key_type;
	typedef typename _Traits_t::value_type value_type;
	typedef typename _Traits_t::key_compare key_compare;
	typedef typename _Traits_t::value_compare value_compare;

	typedef int size_type;
	typedef int difference_type;
//	typedef _Value_t value_type;
	typedef value_type% reference;
	typedef value_type% const_reference;

	typedef _Mycont_it generic_container;
	typedef value_type generic_value;
	typedef _STLCLR Generic::ContainerBidirectionalIterator<_Value_t>
		generic_iterator;
	typedef _STLCLR Generic::ReverseBidirectionalIterator<_Value_t>
		generic_reverse_iterator;

	typedef _STLCLR GenericPair<iterator, bool> pair_iter_bool;
	typedef _STLCLR GenericPair<iterator, iterator> pair_iter_iter;
	typedef _STLCLR GenericPair<node_type^, bool> _Pairnb;
	typedef _STLCLR GenericPair<node_type^, node_type^> _Pairnn;

	typedef _STLCLR GenericPair<generic_iterator^, bool>
		generic_pair_iter_bool;
	typedef _STLCLR GenericPair<generic_iterator^, generic_iterator^>
		generic_pair_iter_iter;

	// constants
	static const int _Maxsize = MAX_CONTAINER_SIZE;

	static const int _Black = 0;	// colors for a node
	static const int _Red = 1;

	// basics
	tree()
		{	// construct empty tree from default comparator
		_Init();
		}

	tree(tree% _Right)
		:	_Mybase_t(_Right.key_comp())
		{	// construct by copying _Right
		_Init();
		_Copy(%_Right);
		}

	tree% operator=(tree% _Right)
		{	// assign
		if ((Object^)this != %_Right)
			{	// worth doing, do it
			clear();
			_Copy(%_Right);
			}
		return (*this);
		}

	operator _Mycont_it^()
		{	// convert to interface
		return (this);
		}

	// constructors
	explicit tree(key_compare^ _Pred)
		:	_Mybase_t(_Pred)
		{	// construct empty tree from comparator
		_Init();
		}

	// destructor
	~tree()
		{	// destroy the object
		clear();
		_Myhead->_Mycont = nullptr;	// orphan all iterators
		_Myhead = nullptr;
		_Mysize = 0;
		++_Mygen;
		}

	// accessors
	unsigned long get_generation()
		{	// get underlying container generation
		return (_Mygen);
		}

	node_type^ get_node(iterator _Where)
		{	// get node from valid iterator
		node_type^ _Node = (node_type^)_Where.get_node();

		if (_Node == nullptr || _Node->container() != (System::Object^)this)
			throw gcnew System::InvalidOperationException();
		return (_Node);
		}

	node_type^ front_node()
		{	// return leftmost node in tree
		return (head_node()->_Left);
		}

	node_type^ back_node()
		{	// return rightmost node in tree
		return (head_node()->_Right);
		}

	node_type^ root_node()
		{	// return root of tree
		return (head_node()->_Parent);
		}

	node_type^ head_node()
		{	// get head node
		return (_Myhead);
		}

//	property reference default[/* size_type */];
//	property value_type front_item;
//	property value_type back_item;
//	reference front();
//	reference back();

	// converters
	_Myarray_t^ to_array()
		{	// convert to array
		_Myarray_t^ _Ans = gcnew _Myarray_t(size());
		node_type^ _Node = head_node();

		for (int _Idx = size(); 0 <= --_Idx; )
			{	// copy back to front
			_Node = _Node->prev_node();
			_Ans[_Idx] = _Node->_Myval;
			}
		return (_Ans);
		}

	key_compare^ key_comp() new
		{	// return object for comparing keys
		return (_Mybase_t::key_comp());
		}

	value_compare^ value_comp() new
		{	// return object for comparing keys
		return (_Mybase_t::value_comp());
		}

	// iterator generators
	iterator make_iterator(node_type^ _Node)
		{	// return iterator for node
		return (iterator(_Node));
		}

	iterator begin()
		{	// return iterator for beginning of mutable sequence
		return (make_iterator(front_node()));
		}

	iterator end()
		{	// return iterator for end of mutable sequence
		return (make_iterator(head_node()));
		}

	reverse_iterator rbegin()
		{	// return reverse iterator for beginning of mutable sequence
		return (reverse_iterator(end()));
		}

	reverse_iterator rend()
		{	// return reverse iterator for end of mutable sequence
		return (reverse_iterator(begin()));
		}

	// size controllers
//	void reserve(size_type _Capacity);
//	size_type capacity();
//	void resize(size_type _Newsize);
//	void resize(size_type _Newsize, value_type _Val);

	size_type size()
		{	// return length of sequence
		return (_Mysize);
		}

	bool empty()
		{	// test if sequence is empty
		return (size() == 0);
		}

	// mutators
//	void push_front(value_type _Val);
//	void pop_front();
//	void push_back(value_type _Val);
//	void pop_back();

//	void assign(size_type _Count, value_type _Val);
//	template<typename _Iter_t>
//		void assign(_Iter_t _First, _Iter_t _Last);
//	void assign(System::Collections::Generic::IEnumerable<_Value_t>^);

	pair_iter_bool insert(value_type _Val)
		{	// try to insert node with value _Val, return iterator, bool
		_Pairnb _Ans = insert_node(_Val);

		return (pair_iter_bool(iterator(_Ans.first),
			_Ans.second));
		}

	iterator insert(iterator _Where, value_type _Val)
		{	// try to insert node with value _Val at _Where, return iterator
		return (make_iterator(insert_node(get_node(_Where), _Val)));
		}

	template<typename _Iter_t>
		void insert(_Iter_t _First, _Iter_t _Last)
		{	// insert [_First, _Last) one at a time
#pragma warning(push)
#pragma warning(disable: 4127)
		if (_Iter_container(_First) != this)
			for (; _First != _Last; ++_First)
				insert_node(*_First);
		else if (_Multi)
			{	// worth assigning to self
			node_type^ _Node = nullptr;

			for (; _First != _Last; ++_First)
				_Node = _Buynode(nullptr, nullptr, _Node,
					(value_type)*_First, 0);
			for (; _Node != nullptr; _Node = _Node->_Right)
				insert_node(_Node->_Myval);	// insert accumulated sequence
			}
#pragma warning(pop)
		}

	void insert(
		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
		_STLCLR Generic::IInputIterator<_Value_t>^ _Last)
		{	// insert [_First, _Last) one at a time
#pragma warning(push)
#pragma warning(disable: 4127)
		if (_Iter_container(_First) != this)
			for (; !_First->equal_to(_Last); _First->next())
				insert_node((value_type%)_First->get_cref());
		else if (_Multi)
			{	// worth assigning to self
			node_type^ _Node = nullptr;

			for (; !_First->equal_to(_Last); _First->next())
				_Node = _Buynode(nullptr, nullptr, _Node,
					(value_type)_First->get_cref(), 0);
			for (; _Node != nullptr; _Node = _Node->_Right)
				insert_node(_Node->_Myval);	// insert accumulated sequence
			}
#pragma warning(pop)
		}

	void insert(_Myenum_it^ _Right)
		{	// insert enumerable
		node_type^ _Node = nullptr;

		for each (value_type _Val in _Right)
			_Node = _Buynode(nullptr, nullptr, _Node,
				_Val, 0);
		for (; _Node != nullptr; _Node = _Node->_Right)
			insert_node(_Node->_Myval);	// insert accumulated sequence
		}

//	void insert(iterator _Where, size_type _Count, value_type _Val);
//	template<typename _Iter_t>
//		void insert(iterator _Where, _Iter_t _First, _Iter_t _Last);
//	void insert(iterator _Where,
//		System::Collections::Generic::IEnumerable<_Value_t>^ _Right);

	void insert_iter(
		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
		_STLCLR Generic::IInputIterator<_Value_t>^ _Last)
		{	// insert [_First, _Last) one at a time
#pragma warning(push)
#pragma warning(disable: 4127)
		if (_First->container() != this)
			for (; !_First->equal_to(_Last); _First->next())
				insert_node((value_type%)_First->get_cref());
		else if (_Multi)
			{	// worth assigning to self
			node_type^ _Node = nullptr;

			for (; !_First->equal_to(_Last); _First->next())
				_Node = _Buynode(nullptr, nullptr, _Node,
					(value_type%)_First->get_cref(), 0);
			for (; _Node != nullptr; _Node = _Node->_Right)
				insert_node(_Node->_Myval);	// insert accumulated sequence
			}
#pragma warning(pop)
		}

	_Pairnb insert_node(value_type _Val)
		{	// try to insert node with value _Val, return node pointer, bool
#pragma warning(push)
#pragma warning(disable: 4127)
		node_type^ _Node = root_node();
		node_type^ _Where = head_node();
		bool _Addleft = true;	// add to left of head if tree empty

		while (!_Node->is_head())
			{	// look for leaf to insert before (_Addleft) or after
			_Where = _Node;
			_Addleft = this->comp(this->get_key(_Val), _Key(_Node));
			_Node = _Addleft ? _Node->_Left : _Node->_Right;
			}

		if (this->_Multi)
			return (_Pairnb(_Insert_node(_Addleft, _Where, _Val),
				true));
		else
			{	// insert only if unique
			if (!_Addleft)
				_Node = _Where;	// need to test if insert after is okay
			else if (_Where == front_node())
				return (_Pairnb(_Insert_node(true, _Where, _Val),
					true));
			else	// need to test if before is okay
				_Node = _Where->prev_node();

			if (this->comp(_Key(_Node), this->get_key(_Val)))
				return (_Pairnb(_Insert_node(_Addleft, _Where, _Val),
					true));
			else
				return (_Pairnb(_Node, false));
			}
#pragma warning(pop)
		}

	node_type^ insert_node(node_type^ _Where_node, value_type _Val)
		{	// try to insert node with value _Val at _Where, return node
#pragma warning(push)
#pragma warning(disable: 4127)
		node_type^ _Where = (node_type^)_Where_node;
		node_type^ _Next;

		if (_Where->container() != this)
			throw gcnew System::ArgumentException();

		if (empty())
			return (_Insert_node(true, head_node(), _Val));
		else if (this->_Multi)
			{	// insert even if duplicate
			if (_Where == front_node())
				{	// insert at beginning if before first element
				if (!this->comp(_Key(_Where), this->get_key(_Val)))
					return (_Insert_node(true, _Where, _Val));
				}
			else if (_Where == head_node())
				{	// insert at end if after last element
				if (!this->comp(this->get_key(_Val), _Key(back_node())))
					return (_Insert_node(false, back_node(), _Val));
				}
			else if (!this->comp(_Key(_Where), this->get_key(_Val))
				&& !this->comp(this->get_key(_Val),
					_Key(_Next = _Where->prev_node())))
				{	// insert before _Where
				if (_Next->_Right->is_head())
					return (_Insert_node(false, _Next, _Val));
				else
					return (_Insert_node(true, _Where, _Val));
				}
			else if (!this->comp(this->get_key(_Val), _Key(_Where))
				&& ((_Next = _Where->next_node())
					== head_node()
					|| !this->comp(_Key(_Next), this->get_key(_Val))))
				{	// insert after _Where
				if (_Where->_Right->is_head())
					return (_Insert_node(false, _Where, _Val));
				else
					return (_Insert_node(true, _Next, _Val));
				}
			}
		else
			{	// insert only if unique
			if (_Where == front_node())
				{	// insert at beginning if before first element
				if (this->comp(this->get_key(_Val), _Key(_Where)))
					return (_Insert_node(true, _Where, _Val));
				}
			else if (_Where == head_node())
				{	// insert at end if after last element
				if (this->comp(_Key(back_node()), this->get_key(_Val)))
					return (_Insert_node(false, back_node(), _Val));
				}
			else if (this->comp(this->get_key(_Val), _Key(_Where))
				&& this->comp(_Key(
					_Next = _Where->prev_node()),
					this->get_key(_Val)))
				{	// insert before _Where
				if (_Next->_Right->is_head())
					return (_Insert_node(false, _Next, _Val));
				else
					return (_Insert_node(true, _Where, _Val));
				}
			else if (this->comp(_Key(_Where), this->get_key(_Val))
				&& ((_Next = _Where->next_node())
					== head_node()
					|| this->comp(this->get_key(_Val), _Key(_Next))))
				{	// insert after _Where
				if (_Where->_Right->is_head())
					return (_Insert_node(false, _Where, _Val));
				else
					return (_Insert_node(true, _Next, _Val));
				}
			}

		return (insert_node(_Val).first);	// try usual insert
#pragma warning(pop)
		}

	iterator erase(iterator _Where)
		{	// erase element at _Where
		return (make_iterator(erase_node(get_node(_Where))));
		}

	iterator erase(iterator _First, iterator _Last)
		{	// erase [_First, _Last)
		node_type^ _First_node = get_node(_First);
		node_type^ _Last_node = get_node(_Last);

		if (_First_node == front_node() && _Last_node == head_node())
			clear();	// erase all
		else
			for (; _First_node != _Last_node; )
				_First_node = erase_node(_First_node);
		return (_Last);
		}

	size_type erase(key_type _Keyval)
		{	// erase and count all that match _Keyval
		node_type^ _First = lower_bound_node(_Keyval);
		node_type^ _Last = upper_bound_node(_Keyval);
		size_type _Num = 0;

		for (; _First != _Last; ++_Num)
			_First = erase_node(_First);	// erase an element matching key
		return (_Num);
		}

	node_type^ erase_node(node_type^ _Where_node)
		{	// erase node _Where
		node_type^ _Where = (node_type^)_Where_node;
		node_type^ _Next = _Where->next_node();	// for return value
		node_type^ _Fixnode;	// the node to recolor as needed
		node_type^ _Fixnodeparent;	// parent of _Fixnode (may be nil)
		node_type^ _Node = _Where;	// the node to erase

		if (_Where->container() != this)
			throw gcnew System::InvalidOperationException();

		if (_Node->_Left->is_head())
			_Fixnode = _Node->_Right;	// must stitch up right subtree
		else if (_Node->_Right->is_head())
			_Fixnode = _Node->_Left;	// must stitch up left subtree
		else
			{	// two subtrees, must lift successor node to replace erased
			_Node = _Next;	// _Node is successor node
			_Fixnode = _Node->_Right;	// _Fixnode is its only subtree
			}

		if (_Node == _Where)
			{	// at most one subtree, relink it
			_Fixnodeparent = _Where->_Parent;
			if (!_Fixnode->is_head())
				_Fixnode->_Parent = _Fixnodeparent;	// link up

			if (root_node() == _Where)
				head_node()->_Parent = _Fixnode;	// link down from root
			else if (_Fixnodeparent->_Left == _Where)
				_Fixnodeparent->_Left = _Fixnode;	// link down to left
			else
				_Fixnodeparent->_Right = _Fixnode;	// link down to right

			if (front_node() == _Where)
				head_node()->_Left = _Fixnode->is_head()
					? _Fixnodeparent	// smallest is parent of erased node
					: _Fixnode->min_node();	// smallest in relinked subtree

			if (back_node() == _Where)
				head_node()->_Right = _Fixnode->is_head()
					? _Fixnodeparent	// largest is parent of erased node
					: _Fixnode->max_node();	// largest in relinked subtree
			}
		else
			{	// erased has two subtrees, _Node is successor to erased
			_Where->_Left->_Parent = _Node;	// link left up
			_Node->_Left = _Where->_Left;	// link successor down

			if (_Node == _Where->_Right)
				_Fixnodeparent = _Node;	// successor is next to erased
			else
				{	// successor further down, link in place of erased
				_Fixnodeparent = _Node->_Parent;	// parent is successor's
				if (!_Fixnode->is_head())
					_Fixnode->_Parent = _Fixnodeparent;	// link fix up
				_Fixnodeparent->_Left = _Fixnode;	// link fix down
				_Node->_Right = _Where->_Right;	// link successor down
				_Where->_Right->_Parent = _Node;	// link right up
				}

			if (root_node() == _Where)
				head_node()->_Parent = _Node;	// link down from root
			else if (_Where->_Parent->_Left == _Where)
				_Where->_Parent->_Left = _Node;	// link down to left
			else
				_Where->_Parent->_Right = _Node;	// link down to right

			_Node->_Parent = _Where->_Parent;	// link successor up

			signed char _Color = _Node->_Color;

			_Node->_Color = _Where->_Color;
			_Where->_Color = _Color;	// recolor it
			}

		if (_Where->_Color == _Black)
			{	// erasing black link, must recolor/rebalance tree
			for (; _Fixnode != root_node() && _Fixnode->_Color == _Black;
				_Fixnodeparent = _Fixnode->_Parent)
				if (_Fixnode == _Fixnodeparent->_Left)
					{	// fixup left subtree
					_Node = _Fixnodeparent->_Right;
					if (_Node->_Color == _Red)
						{	// rotate red up from right subtree
						_Node->_Color = _Black;
						_Fixnodeparent->_Color = _Red;
						_Lrotate(_Fixnodeparent);
						_Node = _Fixnodeparent->_Right;
						}

					if (_Node->is_head())
						_Fixnode = _Fixnodeparent;	// shouldn't happen
					else if (_Node->_Left->_Color == _Black
						&& _Node->_Right->_Color == _Black)
						{	// redden right subtree with black children
						_Node->_Color = _Red;
						_Fixnode = _Fixnodeparent;
						}
					else
						{	// must rearrange right subtree
						if (_Node->_Right->_Color == _Black)
							{	// rotate red up from left sub-subtree
							_Node->_Left->_Color = _Black;
							_Node->_Color = _Red;
							_Rrotate(_Node);
							_Node = _Fixnodeparent->_Right;
							}

						_Node->_Color = _Fixnodeparent->_Color;
						_Fixnodeparent->_Color = _Black;
						_Node->_Right->_Color = _Black;
						_Lrotate(_Fixnodeparent);
						break;	// tree now recolored/rebalanced
						}
					}
				else
					{	// fixup right subtree
					_Node = _Fixnodeparent->_Left;
					if (_Node->_Color == _Red)
						{	// rotate red up from left subtree
						_Node->_Color = _Black;
						_Fixnodeparent->_Color = _Red;
						_Rrotate(_Fixnodeparent);
						_Node = _Fixnodeparent->_Left;
						}
					if (_Node->is_head())
						_Fixnode = _Fixnodeparent;	// shouldn't happen
					else if (_Node->_Right->_Color == _Black
						&& _Node->_Left->_Color == _Black)
						{	// redden left subtree with black children
						_Node->_Color = _Red;
						_Fixnode = _Fixnodeparent;
						}
					else
						{	// must rearrange left subtree
						if (_Node->_Left->_Color == _Black)
							{	// rotate red up from right sub-subtree
							_Node->_Right->_Color = _Black;
							_Node->_Color = _Red;
							_Lrotate(_Node);
							_Node = _Fixnodeparent->_Left;
							}

						_Node->_Color = _Fixnodeparent->_Color;
						_Fixnodeparent->_Color = _Black;
						_Node->_Left->_Color = _Black;
						_Rrotate(_Fixnodeparent);
						break;	// tree now recolored/rebalanced
						}
					}

			_Fixnode->_Color = _Black;	// ensure stopping node is black
			}

		_Mybase_t::unmake_value(_Where->_Myval);
		_Where->_Head = nullptr;	// orphan corresponding iterators
		--_Mysize;
		++_Mygen;
		return (_Next);
		}

	void clear()
		{	// erase all
		for (; front_node() != head_node(); )
			erase_node(front_node());
		}

	void swap(_Mytype_t% _Right)
		{	// exchange contents with _Right
		if ((Object^)this != %_Right)
			{	// worth doing, swap
			tree^ _Temp = gcnew tree(_Right);

			_Right._Copy(this);
			_Copy(_Temp);
			}
		}

	// searches
	iterator find(key_type _Keyval)
		{	// find an element that matches _Keyval, return iterator
		node_type^ _Where = lower_bound_node(_Keyval);

		return (make_iterator(_Where == head_node()
			|| this->comp(_Keyval, _Key(_Where))
				? head_node() : _Where));
		}

	size_type count(key_type _Keyval)
		{	// count all elements that match _Keyval
		node_type^ _First = lower_bound_node(_Keyval);
		node_type^ _Last = upper_bound_node(_Keyval);
		size_type _Num = 0;

		for (; _First != _Last; _First = _First->next_node())
			++_Num;
		return (_Num);
		}

	iterator lower_bound(key_type _Keyval)
		{	// find leftmost node not less than _Keyval
		return (make_iterator(lower_bound_node(_Keyval)));
		}

	node_type^ lower_bound_node(key_type _Keyval)
		{	// find leftmost node not less than _Keyval
		node_type^ _Node = root_node();
		node_type^ _Where = head_node();	// end() if search fails

		while (!_Node->is_head())
			if (this->comp(_Key(_Node), _Keyval))
				_Node = _Node->_Right;	// descend right subtree
			else
				{	// _Node not less than _Keyval, remember it
				_Where = _Node;
				_Node = _Node->_Left;	// descend left subtree
				}

		return (_Where);	// return best remembered candidate
		}

	iterator upper_bound(key_type _Keyval)
		{	// find leftmost node greater than _Keyval
		return (make_iterator(upper_bound_node(_Keyval)));
		}

	node_type^ upper_bound_node(key_type _Keyval)
		{	// find leftmost node greater than _Keyval
		node_type^ _Node = root_node();
		node_type^ _Where = head_node();	// end() if search fails

		while (!_Node->is_head())
			if (this->comp(_Keyval, _Key(_Node)))
				{	// _Node greater than _Keyval, remember it
				_Where = _Node;
				_Node = _Node->_Left;	// descend left subtree
				}
			else
				_Node = _Node->_Right;	// descend right subtree

		return (_Where);	// return best remembered candidate
		}

	pair_iter_iter equal_range(key_type _Keyval)
		{	// find range equivalent to _Keyval
		_Pairnn _Ans = equal_range_node(_Keyval);
		return (pair_iter_iter(iterator(_Ans.first),
			iterator(_Ans.second)));
		}

	_Pairnn equal_range_node(key_type _Keyval)
		{	// find range equivalent to _Keyval
		return (_Pairnn(lower_bound_node(_Keyval),
			upper_bound_node(_Keyval)));
		}

_STLCLR_FIELD_ACCESS:
	node_type^ _Buynode()
		{	// allocate a head node and set links
		node_type^ _Node = gcnew node_type;

		_Node->_Left = _Node;
		_Node->_Parent = _Node;
		_Node->_Right = _Node;
		_Node->_Head = _Node;
		_Node->_Color = _Black;
		_Node->_Mycont = this;
		return (_Node);
		}

	node_type^ _Buynode(node_type^ _Larg, node_type^ _Parg,
		node_type^ _Rarg, value_type _Val, signed char _Carg)
		{	// allocate a node and set links
		node_type^ _Node = gcnew node_type(
				_Larg, _Parg, _Rarg, _Myhead, _Val, _Carg);

		return (_Node);
		}

	void _Chown(node_type^ _Node, node_type^ _Head, tree^ _Owner)
		{	// change ownership of subtree
		if (_Node->_Left->is_head())
			_Node->_Left = _Head;
		else
			_Chown(_Node->_Left, _Head, _Owner);

		if (_Node->_Right->is_head())
			_Node->_Right = _Head;
		else
			_Chown(_Node->_Right, _Head, _Owner);

		if (_Node->is_head())
			_Node->_Parent = _Head;

		_Node->_Mycont = _Owner;
		}

	void _Copy(tree^ _Right)
		{	// copy entire tree from _Right
		_Myhead->_Parent = _Copy(_Right->root_node(), head_node());
		_Mysize = _Right->size();
		if (!root_node()->is_head())
			{	// nonempty tree, look for new smallest and largest
			head_node()->_Left = root_node()->min_node();
			head_node()->_Right = root_node()->max_node();
			}
		else
			{	// empty tree, cauterize smallest and largest
			head_node()->_Left = head_node();
			head_node()->_Right = head_node();
			}
		++_Mygen;
		}

	node_type^ _Copy(node_type^ _Oldroot,
		node_type^ _Newparent)
		{	// copy entire subtree, recursively
		node_type^ _Newroot = head_node();

		if (!_Oldroot->is_head())
			{	// copy a node, then any subtrees
			node_type^ _Node = _Buynode(head_node(), _Newparent,
				head_node(), _Oldroot->_Myval, _Oldroot->_Color);

			if (_Newroot->is_head())
				_Newroot = _Node;	// memorize new root first time

			_Node->_Left = _Copy(_Oldroot->_Left, _Node);
			_Node->_Right = _Copy(_Oldroot->_Right, _Node);
			}
		return (_Newroot);
		}

	void _Init()
		{	// create header/nil node and make tree empty
		_Mysize = 0;
		_Myhead = _Buynode();
		_Mygen = 0;
		}

	node_type^ _Insert_node(bool _Addleft, node_type^ _Where,
		value_type _Val)
		{	// add node with value next to _Where, to left if _Addleft

		if (_Maxsize <= _Mysize)
			throw gcnew System::InvalidOperationException();

		node_type^ _Newnode = _Buynode(head_node(), _Where, head_node(),
			_Val, _Red);

		if (_Where == head_node())
			{	// first node in tree, just set head values
			head_node()->_Left = _Newnode;
			head_node()->_Parent = _Newnode;
			head_node()->_Right = _Newnode;
			}
		else if (_Addleft)
			{	// add to left of _Where
			_Where->_Left = _Newnode;
			if (_Where == front_node())
				head_node()->_Left = _Newnode;
			}
		else
			{	// add to right of _Where
			_Where->_Right = _Newnode;
			if (_Where == back_node())
				head_node()->_Right = _Newnode;
			}

		for (node_type^ _Node = _Newnode;
			_Node->_Parent->_Color == _Red; )
			if (_Node->_Parent == _Node->_Parent->_Parent->_Left)
				{	// fixup red-red in left subtree
				_Where = _Node->_Parent->_Parent->_Right;
				if (_Where->_Color == _Red)
					{	// parent has two red children, blacken both
					_Node->_Parent->_Color = _Black;
					_Where->_Color = _Black;
					_Node->_Parent->_Parent->_Color = _Red;
					_Node = _Node->_Parent->_Parent;
					}
				else
					{	// parent has red and black children
					if (_Node == _Node->_Parent->_Right)
						{	// rotate right child to left
						_Node = _Node->_Parent;
						_Lrotate(_Node);
						}
					_Node->_Parent->_Color = _Black;	// propagate red up
					_Node->_Parent->_Parent->_Color = _Red;
					_Rrotate(_Node->_Parent->_Parent);
					}
				}
			else
				{	// fixup red-red in right subtree
				_Where = _Node->_Parent->_Parent->_Left;
				if (_Where->_Color == _Red)
					{	// parent has two red children, blacken both
					_Node->_Parent->_Color = _Black;
					_Where->_Color = _Black;
					_Node->_Parent->_Parent->_Color = _Red;
					_Node = _Node->_Parent->_Parent;
					}
				else
					{	// parent has red and black children
					if (_Node == _Node->_Parent->_Left)
						{	// rotate left child to right
						_Node = _Node->_Parent;
						_Rrotate(_Node);
						}
					_Node->_Parent->_Color = _Black;	// propagate red up
					_Node->_Parent->_Parent->_Color = _Red;
					_Lrotate(_Node->_Parent->_Parent);
					}
				}

		root_node()->_Color = _Black;	// root is always black
		++_Mysize;
		++_Mygen;
		return (_Newnode);
		}

	key_type _Key(node_type^ _Where)
		{	// get key value from node
		return (this->get_key(_Where->_Myval));
		}

	void _Lrotate(node_type^ _Where)
		{	// promote right node to root of subtree
		node_type^ _Node = _Where->_Right;
		_Where->_Right = _Node->_Left;

		if (!_Node->_Left->is_head())
			_Node->_Left->_Parent = _Where;
		_Node->_Parent = _Where->_Parent;

		if (_Where == root_node())
			head_node()->_Parent = _Node;
		else if (_Where == _Where->_Parent->_Left)
			_Where->_Parent->_Left = _Node;
		else
			_Where->_Parent->_Right = _Node;

		_Node->_Left = _Where;
		_Where->_Parent = _Node;
		}

	void _Rrotate(node_type^ _Where)
		{	// promote left node to root of subtree
		node_type^ _Node = _Where->_Left;
		_Where->_Left = _Node->_Right;

		if (!_Node->_Right->is_head())
			_Node->_Right->_Parent = _Where;
		_Node->_Parent = _Where->_Parent;

		if (_Where == root_node())
			head_node()->_Parent = _Node;
		else if (_Where == _Where->_Parent->_Right)
			_Where->_Parent->_Right = _Node;
		else
			_Where->_Parent->_Left = _Node;

		_Node->_Right = _Where;
		_Where->_Parent = _Node;
		}

	// data members
	node_type^ _Myhead;	// pointer to head node
	size_type _Mysize;	// number of elements
	unsigned long _Mygen;	// current change generation

	// interfaces
public:
	virtual System::Object^ Clone()
		{	// clone the tree
		return (gcnew tree(*this));
		}

private:
	property size_type Count
		{	// element count
		virtual size_type get() sealed
			= System::Collections::ICollection::Count::get
			{	// get element count
			return (size());
			}
		};

	property bool IsSynchronized
		{	// synchronized status
		virtual bool get() sealed
			= System::Collections::ICollection::IsSynchronized::get
			{	// test if synchronized
			return (false);
			}
		};

	property System::Object^ SyncRoot
		{	// synchronizer
		virtual System::Object^ get() sealed
			= System::Collections::ICollection::SyncRoot::get
			{	// get synchronizer
			return (this);
			}
		};

	virtual void CopyTo(System::Array^ _Dest_arg, int _First) sealed
		= System::Collections::ICollection::CopyTo
		{	// copy to _Dest_arg, beginning at _First
		cli::array<System::Object^>^ _Dest =
			(cli::array<System::Object ^>^)_Dest_arg;
		node_type^ _Node = head_node();

		for (int _Idx = size(); 0 <= --_Idx; )
			{	// copy back to front
			_Node = _Node->prev_node();
			_Dest[_First + _Idx] = _Node->_Myval;
			}
		}

	virtual System::Collections::IEnumerator^ GetEnumerator() sealed
		= System::Collections::IEnumerable::GetEnumerator
		{	// get enumerator for the container
		return (gcnew
			_STLCLR TreeEnumerator<_Key_t, _Value_t>(front_node()));
		}

	virtual unsigned long get_generation_virtual() sealed
		= _Mycont_it::get_generation
		{	// get underlying container generation
		return (get_generation());
		}

//	virtual bool valid_bias_virtual(size_type _Bias);
//	virtual reference at_virtual(size_type _Pos);
//	virtual reference at_bias_virtual(size_type _Bias);

//	virtual reference front_virtual();
//	virtual reference back_virtual();

	// converters
	virtual key_compare^ key_comp_virtual() sealed
		= _Mycont_it::key_comp
		{	// return object for comparing keys
		return (key_comp());
		}

	virtual value_compare^ value_comp_virtual() sealed
		= _Mycont_it::value_comp
		{	// return object for comparing keys
		return (value_comp());
		}

	// iterator generators
	virtual generic_iterator begin_virtual() sealed
		= _Mycont_it::begin
		{	// return iterator for beginning of mutable sequence
		return (begin());
		}
	virtual generic_iterator end_virtual() sealed
		= _Mycont_it::end
		{	// return iterator for end of mutable sequence
		return (end());
		}

	virtual generic_reverse_iterator rbegin_virtual() sealed
		= _Mycont_it::rbegin
		{	// return reverse iterator for beginning of mutable sequence
		return (generic_reverse_iterator(end()));
		}

	virtual generic_reverse_iterator rend_virtual() sealed
		= _Mycont_it::rend
		{	// return reverse iterator for end of mutable sequence
		return (generic_reverse_iterator(begin()));
		}

	// size controllers
//	virtual void reserve_virtual(size_type _Capacity);
//	virtual size_type capacity_virtual();
//	virtual void resize_virtual(size_type _Newsize);
//	virtual void resize_virtual(size_type _Newsize, value_type _Val);

	virtual size_type size_virtual() sealed
		= _Mycont_it::size
		{	// return length of sequence
		return (size());
		}

	virtual bool empty_virtual() sealed
		= _Mycont_it::empty
		{	// test if sequence is empty
		return (empty());
		}

	// mutators
//	virtual void push_front_virtual(value_type _Val);
//	virtual void pop_front_virtual();
//	virtual void push_back_virtual(value_type _Val);
//	virtual void pop_back_virtual();

//	virtual void assign_virtual(size_type _Count, value_type _Val);
//	virtual void assign_virtual(
//		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
//		_STLCLR Generic::IInputIterator<_Value_t>^ _Last);
//	virtual void assign_virtual(_Myenum_it^ _Right);

	virtual generic_pair_iter_bool insert_virtual(value_type _Val) sealed
		= _Mycont_it::insert
		{	// try to insert node with value _Val, return iterator, bool
		_Pairnb _Ans = insert_node(_Val);
		return (generic_pair_iter_bool(gcnew generic_iterator(_Ans.first),
			_Ans.second));
		}

	virtual generic_iterator insert_virtual(generic_iterator _Where,
		value_type _Val) sealed
		= _Mycont_it::insert
		{	// insert _Val at _Where
		return (insert(iterator(_Where), _Val));
		}

//	virtual void insert_virtual(generic_iterator _Where,
//		size_type _Count, value_type _Val);
//	virtual void insert_virtual(generic_iterator _Where_iter,
//		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
//		_STLCLR Generic::IInputIterator<_Value_t>^ _Last);
//	virtual void insert_virtual(generic_iterator _Where_iter,
//		_Myenum_it^ _Right);

	virtual void insert_virtual(
		_STLCLR Generic::IInputIterator<_Value_t>^ _First,
		_STLCLR Generic::IInputIterator<_Value_t>^ _Last) sealed
		= _Mycont_it::insert
		{	// insert [_First, _Last) one at a time
		insert(_First, _Last);
		}

	virtual void insert_virtual(_Myenum_it^ _Right) sealed
		= _Mycont_it::insert
		{	// insert enumerable
		insert(_Right);
		}

	virtual generic_iterator erase_virtual(generic_iterator _Where) sealed
		= _Mycont_it::erase
		{	// erase element at _Where
		return (erase(iterator(_Where)));
		}

	virtual generic_iterator erase_virtual(generic_iterator _First,
		generic_iterator _Last) sealed
		= _Mycont_it::erase
		{	// erase [_First, _Last)
		return (erase(iterator(_First), iterator(_Last)));
		}

	virtual size_type erase_virtual(key_type _Keyval) sealed
		= _Mycont_it::erase
		{	// erase and count all that match _Keyval
		return (erase(_Keyval));
		}

	virtual void clear_virtual() sealed
		= _Mycont_it::clear
		{	// erase all
		clear();
		}

	virtual void swap_virtual(_Mycont_it^ _Right) sealed
		= _Mycont_it::swap
		{	// exchange contents with _Right
		swap(*(_Mytype_t^)_Right);
		}

	// searches
	virtual generic_iterator find_virtual(key_type _Keyval) sealed
		= _Mycont_it::find
		{	// find an element that matches _Keyval, return iterator
		return (find(_Keyval));
		}

	virtual size_type count_virtual(key_type _Keyval) sealed
		= _Mycont_it::count
		{	// count all elements that match _Keyval
		return (count(_Keyval));
		}

	virtual generic_iterator lower_bound_virtual(key_type _Keyval) sealed
		= _Mycont_it::lower_bound
		{	// find leftmost node not less than _Keyval
		return (lower_bound(_Keyval));
		}

	virtual generic_iterator upper_bound_virtual(key_type _Keyval) sealed
		= _Mycont_it::upper_bound
		{	// find leftmost node greater than _Keyval
		return (upper_bound(_Keyval));
		}

	virtual generic_pair_iter_iter equal_range_virtual(
		key_type _Keyval) sealed
			= _Mycont_it::equal_range
		{	// find range equivalent to _Keyval
		_Pairnn _Ans = equal_range_node(_Keyval);
		return (generic_pair_iter_iter(gcnew generic_iterator(_Ans.first),
			gcnew generic_iterator(_Ans.second)));
		}
	};
	}	// namespace cliext::impl

//
// TEMPLATE COMPARISONS
//
template<typename _Traits_t> inline
	bool operator==(cliext::impl::tree<_Traits_t>% _Left,
		cliext::impl::tree<_Traits_t>% _Right)
	{	// test if _Left == _Right
	typedef cliext::impl::tree<_Traits_t> _Mytype_t;

	_Mytype_t::size_type _Size = _Left.size();

	if (_Size != _Right.size())
		return (false);
	else
		{	// same length, compare elements
		_Mytype_t::node_type^ _Pleft = _Left.front_node();
		_Mytype_t::node_type^ _Pright = _Right.front_node();
		_Mytype_t::key_compare^ _Pred = _Left.key_comp();

		for (; 0 < _Size; --_Size)
			{	// compare next two elements
				if (_Pred(_Left.get_key(_Pleft->_Myval),
						_Right.get_key(_Pright->_Myval))
					|| _Pred(_Right.get_key(_Pright->_Myval),
						_Left.get_key(_Pleft->_Myval)))
				return (false);
			_Pleft = _Pleft->next_node();
			_Pright = _Pright->next_node();
			}
		return (true);
		}
	}

template<typename _Traits_t> inline
	bool operator!=(cliext::impl::tree<_Traits_t>% _Left,
		cliext::impl::tree<_Traits_t>% _Right)
	{	// test if _Left != _Right
	return (!(_Left == _Right));
	}

template<typename _Traits_t> inline
	bool operator<(cliext::impl::tree<_Traits_t>% _Left,
		cliext::impl::tree<_Traits_t>% _Right)
	{	// test if _Left < _Right
	typedef cliext::impl::tree<_Traits_t> _Mytype_t;

	_Mytype_t::size_type _Idx = 0;
	_Mytype_t::node_type^ _Pleft = _Left.front_node();
	_Mytype_t::node_type^ _Pright = _Right.front_node();
	_Mytype_t::key_compare^ _Pred = _Left.key_comp();

	for (; _Idx != _Left.size() && _Idx != _Right.size(); ++_Idx)
		{	// compare next two elements
		if (_Pred(_Left.get_key(_Pleft->_Myval),
			_Right.get_key(_Pright->_Myval)))
			return (true);
		else if (_Pred(_Right.get_key(_Pright->_Myval),
			_Left.get_key(_Pleft->_Myval)))
			return (false);
		_Pleft = _Pleft->next_node();
		_Pright = _Pright->next_node();
		}
	return (_Idx == _Left.size() && _Idx != _Right.size());
	}

template<typename _Traits_t> inline
	bool operator>=(cliext::impl::tree<_Traits_t>% _Left,
		cliext::impl::tree<_Traits_t>% _Right)
	{	// test if _Left >= _Right
	return (!(_Left < _Right));
	}

template<typename _Traits_t> inline
	bool operator>(cliext::impl::tree<_Traits_t>% _Left,
		cliext::impl::tree<_Traits_t>% _Right)
	{	// test if _Left > _Right
	return (_Right < _Left);
	}

template<typename _Traits_t> inline
	bool operator<=(cliext::impl::tree<_Traits_t>% _Left,
		cliext::impl::tree<_Traits_t>% _Right)
	{	// test if _Left <= _Right
	return (!(_Right < _Left));
	}

//
// TEMPLATE FUNCTION swap
//
template<typename _Traits_t> inline
	void swap(cliext::impl::tree<_Traits_t>% _Left,
		cliext::impl::tree<_Traits_t>% _Right)
	{	// swap two trees
	_Left.swap(_Right);
	}
}	// namespace cliext
#endif // _CLI_XTREE_

/*
 * Copyright (c) 2004-2007 by Dinkumware, Ltd.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
V5.03:0009 */
